package com.huawei.codearts.config.version;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.condition.RequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.reflect.Method;
import java.util.Objects;

@Slf4j
public class ApiRequestHandlerMapping extends RequestMappingHandlerMapping {

    public final static String VERSION_FLAG = "{version}";
    public static RequestCondition<ApiVersionCondition> createCondition(Class<?> clazz) {
        RequestMapping classRequestMapping = clazz.getAnnotation(RequestMapping.class);
//        log.info("ApiRequestHandlerMapping...classRequestMapping={}", classRequestMapping);
        if (classRequestMapping == null) {
            return null;
        }
        StringBuilder mappingUrlBuilder = new StringBuilder();
        if (classRequestMapping.value().length > 0) {
            mappingUrlBuilder.append(classRequestMapping.value()[0]);
        }
        String mappingUrl = mappingUrlBuilder.toString();
        if (!mappingUrl.contains(VERSION_FLAG)) {
            return null;
        }
        ApiVersion apiVersion = clazz.getAnnotation(ApiVersion.class);
//        log.info("ApiRequestHandlerMapping...apiVersion={}", apiVersion);
        return apiVersion == null ? new ApiVersionCondition(1):new ApiVersionCondition(apiVersion.value());
    }

    @Override
    protected  RequestCondition<?> getCustomMethodCondition(Method method) {
        ApiVersion apiVersion = AnnotationUtils.findAnnotation(method, ApiVersion.class);
//        System.out.println("getCustomMethodCondition..." + apiVersion);
        if (null == apiVersion) {
            return super.getCustomMethodCondition(method);
        } else {
            return createCondition(method.getClass());
        }
    }

    @Override
    protected  RequestCondition<?> getCustomTypeCondition(Class<?> handlerType) {
        ApiVersion apiVersion = AnnotationUtils.findAnnotation(handlerType, ApiVersion.class);
        if (null == apiVersion) {
            return super.getCustomTypeCondition(handlerType);
        } else {
            return createCondition(handlerType);
        }
    }


    /**
     * 读取基础包配置
     */
    @Value("${api-package}")
    private String bathApiPackagePath;

    /**
     * 重写方法路由获取, 路由增加前缀
     * 例如：v1或v2 文件夹下的controller会自动增加 路由前缀
     * RequestMapping(value = {"api/test"}) 路由会自动加前缀 api/test > v1/api/test
     * @param method
     * @param handlerType
     * @return
     */
    @Override
    protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
        RequestMappingInfo mappingInfo = super.getMappingForMethod(method, handlerType);

        if (Objects.nonNull(mappingInfo)) {
            String prefix = this.getPrefix(handlerType);
//            System.out.println("getMappingForMethod...combine..." + RequestMappingInfo.paths(prefix).build().combine(mappingInfo));
            /**
             * RequestMappingInfo.paths(prefix).build() 根据前缀生成mappingInfo
             * combine(mappingInfo) 拼接原来的mappingInfo
             */
            return RequestMappingInfo.paths(prefix).build().combine(mappingInfo);
        }

        return mappingInfo;
    }

    /**
     * 获取方法路由前缀
     * @param handleType
     * @return
     */
    private String getPrefix(Class<?> handleType) {
        // 严格区分版本
//        String packageName = handleType.getPackage().getName();
//        String dotPath = packageName.replace(this.bathApiPackagePath, "").replace(".","/");
//        return dotPath;
        return "";
    }

}
